/**
 * @desc
 *
 * @使用场景
 *
 * @author  杨晓东[of1081]
 * @company qianmi.com
 * @Date    16/11/21
 **/
'use strict';

let Immutable  =require('immutable');
let fse = require('fs-extra');
let fs =require('fs');
let path  =require('path');
let http = require('http');
let BufferHelper = require('bufferhelper');
let widetUtil =require('@qianmi/x-site-common/util/widget-util');
let templateCompileUtil =  module.exports={};
let exec = require('child_process').execSync;

let ossPrefix = 'http://oss-hz.qianmi.com/x-site/${env}/public/barRepo/';

/**
 * 根据模板配置文件,生成模板加载JS文件...
 * 包含组件集合, 插件
 * @param workBenchPath    模板开发所在路径;
 * @param templateConfigPath    模板配置文件绝对路径;
 */
templateCompileUtil.generateTplInfo = function * ({workBenchPath,templateConfigPath,envCode}){
  //读取模板配置文件内容::
  let templateConfig =  yield this._readTempConfig(templateConfigPath);
  templateConfig =_dealTemplateConfig({templateConfig,templateConfigPath});
  let dependenciesBar  =yield analyseTemplateDependentBar({templateConfig,workBenchPath,envCode});
  templateConfig.dependenciesBar = dependenciesBar;
  return templateConfig;
}

/**
 *
 * 模板模板配置文件 生成模板注入JS
 * @param workBenchPath
 * @param templateConfig
 */
templateCompileUtil.generateTemplateConfigContent = function * ({workBenchPath,templateConfig,envCode}){
  
  let templateJs = '',templateCss ='';
  
  for(let i =0,ilen=templateConfig.dependenciesBar.length ; i<ilen; i++){
    let widgetNs  = templateConfig.dependenciesBar[i];
    let barDefaultPropsMap;
    if(templateConfig.barDefaultPropsMap){
      barDefaultPropsMap = templateConfig.barDefaultPropsMap[widgetNs];
    }
    let {js,css}  =  yield _loadWidgetJSFile(widgetNs,barDefaultPropsMap,workBenchPath,envCode);
    templateJs+=js;
    templateCss+=css;
  }
  
  templateJs +=`;(function(){
     window.__XSite_template_register(${JSON.stringify(templateConfig)});
     xDllContext.iflux.msg.emit("__XSite_Template_Loaded_${templateConfig.templateName}", "${templateConfig.templateName}");
  })();`;
  return  {templateJs,templateCss};
}



/**
 * 加载编译后的JS的代码.
 * @param widgetNs
 * @param widgetDefaultProps
 * @return {{js: *, css: string}}
 * @private
 */
function * _loadWidgetJSFile(widgetNs, widgetDefaultProps,workBenchPath,envCode) {
  let __workbenchName  =  getWorkBenchName(workBenchPath);
  let widgetPath;
  let widgetWorkBench = getNsWorkBenchName(widgetNs);
  let widgetJs = "";
  let widgetPJs = "";
  let widgetCss = "";
  if (__workbenchName === widgetWorkBench) {
    widgetPath = path.join(workBenchPath, './dist/barRepo', widgetNs);
    console.log('加载本项目文件到模板编译文件中');
    console.log('读取每个组件的js -p.js .css',widgetPath,'========================================================');
    [widgetJs,widgetPJs] = yield [loadFile(widgetPath + ".js"), loadFile(widgetPath + "-p.js")];
    try{
      widgetCss  = yield loadFile(widgetPath + ".css");
    }catch(err){
      console.warn(widgetPath + ".css 加载失败, 可能本组件就不需要这个样式文件");
    }
  } else { //依赖外部的 bar
    console.log('加载外部项目文件到模板编译文件中');
    let _path = path.join(workBenchPath, 'temp/' + widgetNs);
    try {
      widgetJs = fse.readFileSync(_path + '.js');
      widgetPJs = fse.readFileSync(_path + '-p.js');
      widgetCss = fse.readFileSync(_path + '.css');
    } catch (e) {
      console.log('从阿里云拿组件，并保存到本地');
      widgetPath = ossPrefix.replace('${env}',envCode) + widgetNs;
      widgetJs = yield download(widgetPath + '.js');
      widgetPJs = yield download(widgetPath + '-p.js');
      if (!widgetJs || !widgetPJs) {
        throw new Error('从阿里云没有取到所依赖的JS或-P文件，'+widgetPath);
      }
      widgetCss = yield download(widgetPath + '.css');
      widgetJs && fse.outputFileSync(_path + '.js', widgetJs);
      widgetPJs && fse.outputFileSync(_path + '-p.js', widgetPJs);
      widgetCss && fse.outputFileSync(_path + '.css', widgetCss);
    }
  }

  //包含组件的转换属性...
  if (widgetDefaultProps) {
    if (typeof widgetDefaultProps === 'function') {
      //把函数源代码赋值过去.
      widgetDefaultProps = widgetDefaultProps.toString();
    } else {
      widgetDefaultProps = JSON.stringify(widgetDefaultProps);
    }
    
    let _begIndex = widgetPJs.indexOf('__XSite_widgetInject');
    let _startIndex = widgetPJs.indexOf('{', _begIndex)+1;
    
    let _preContent = widgetPJs.substring(0, _startIndex);
    let _postContent = widgetPJs.substring(_startIndex);
    
    widgetPJs = _preContent + `widgetDefaultProps:${widgetDefaultProps},` + _postContent
  }
  
  return {js: widgetJs + widgetPJs, css: widgetCss};
  
}

function * loadFile(filePath){
  return new Promise((resolve,reject)=>{
    fs.readFile(filePath, (err, data) => {
      // if (err) throw err;
      err?reject(err):resolve(data.toString());
    });
  });
}

templateCompileUtil._readTempConfig = function * (templateConfigPath) {
  return new Promise((resolve)=>{
    fse.readJson(templateConfigPath, function (err, templateConfig) {
      if(err){
        throw err;
      }else {
        resolve(templateConfig);
      }
    });
  });
}

/**
 * 获取模板配置信息
 * 处理数据重定义,等一些设置的问题..
 * @param templateConfigPath
 */
function  _dealTemplateConfig({templateConfig,templateConfigPath}){
  if(templateConfig.barDefaultPropsMap){//组件条的属性跟着模板走..的转换.
    for(let _widgetNameSpace in templateConfig.barDefaultPropsMap){
      let _widgetBarPropFile =path.join(templateConfigPath,'..',templateConfig.barDefaultPropsMap[_widgetNameSpace]);
      
      if(_widgetBarPropFile.endsWith('.json')){ //  TODO 其实只要JS类型的就可以了,JSON这种类型的包含在其中
        templateConfig.barDefaultPropsMap[_widgetNameSpace]=fse.readJsonSync(_widgetBarPropFile);
      }else if(_widgetBarPropFile.endsWith('.js')){
        templateConfig.barDefaultPropsMap[_widgetNameSpace]=require(_widgetBarPropFile);
      } else {
        throw new Error('默认数据配置不正确!!~'+file);
      }
    }
  }
  
  //children如果是级呢? 这里不需要这个了.
  templateConfig.children=templateConfig.children.map(function(childrenItem){
    if(!childrenItem.widgetNameSpace){
      throw new Error(templateConfigPath+'模板children中widgetNameSpace未定义完整'+JSON.stringify(childrenItem));
    }
    //childrenItem.widgetNameSpace=path.join(dirPath,childrenItem.widgetFile).replace(/\\/g,'/');
    
    if(childrenItem.initPropsFile){
      console.log('把initPropsFile汇总到templateConfig');
      let childrenItemInitProsp = path.join(templateConfigPath,'..',childrenItem.initPropsFile);
      //FileNameSpace=path.join(dirPath,childrenItem.widgetFile).replace(/\\/g,'/');
      if(childrenItem.initPropsFile.endsWith(".json")){
        childrenItem.initProps = require(childrenItemInitProsp);
      } else if(childrenItemInitProsp.endsWith('.js')){
        childrenItem.initProps = require(childrenItemInitProsp);
      }
      console.log('取得的initProps 内容为: ',childrenItem.initProps);
    }
    
    childrenItem.widget=widetUtil.extraWidgetNameFromPath(childrenItem.widgetNameSpace);
    return childrenItem;
  });
  
  if(templateConfig.nsTransferMap){
    console.log('对nsTransferMap进行处理,自动详细记录组件信息');
    for(let platForm  in templateConfig.nsTransferMap){
      let widgetNameMap = {};
      if( templateConfig.nsTransferMap[platForm].barMap){
        for(let ns in  templateConfig.nsTransferMap[platForm].barMap){
          let  toNs =templateConfig.nsTransferMap[platForm].barMap[ns];
          widgetNameMap[widetUtil.extraWidgetNameFromPath(ns)] =widetUtil.extraWidgetNameFromPath(toNs);
        }
      }
      
      if( templateConfig.nsTransferMap[platForm].groupMap){
        for(let ns in  templateConfig.nsTransferMap[platForm].groupMap) {
          let toNs = templateConfig.nsTransferMap[platForm].groupMap[ns];
          widgetNameMap[widetUtil.extraWidgetNameFromPath(ns)] =widetUtil.extraWidgetNameFromPath(toNs);
        }
      }
      
      templateConfig.nsTransferMap[platForm].widgetNameMap = widgetNameMap;
    }
    
  }
  return templateConfig;
}

/**
 * 分析出模板所依赖的所有组件
 * @param templateCnnfig
 */
function * analyseTemplateDependentBar({templateConfig,workBenchPath,envCode}){
  let result =[];
  //console.log('template::',templateConfig.templateName);
  let tasks = [];
  templateConfig.children.forEach(childitem=>{
    //根据一个名命空间, 找出其子元素所有的名命空间
    result.push(childitem.widgetNameSpace);
    tasks.push(searchNameSpaceFromFile(childitem.widgetNameSpace,workBenchPath,envCode));
  });
  
  templateConfig.acceptBars && templateConfig.acceptBars.forEach(barItem=>{
    result.push(barItem);
    tasks.push(searchNameSpaceFromFile(barItem,workBenchPath,envCode));
  });
  
  templateConfig.pluginBars && templateConfig.pluginBars.forEach(barItem=>{
    result.push(barItem);
    tasks.push(searchNameSpaceFromFile(barItem,workBenchPath,envCode));
  });
  
  templateConfig.adapterBars && templateConfig.adapterBars.forEach(barItem=>{
    result.push(barItem);
    tasks.push(searchNameSpaceFromFile(barItem,workBenchPath,envCode));
  });
  
  let arrays = yield tasks;
  arrays.forEach(item=>{
    result = result.concat(item.toJS());
  })
  
  return result;
}

/**
 * 根据指定组件 找到其直接或间接依赖的子组件
 * @param widgetNameSpace 组件命名空间
 * @param topDir 顶部目录
 **/
function * searchNameSpaceFromFile(widgetNameSpace,workBenchPath,envCode){
  let widgetWorkBench = widgetNameSpace.split('/');
  let workBenchName = getWorkBenchName(workBenchPath);
  let barIndex;
  if( widgetWorkBench[0] === workBenchName){
    console.log('===================>',widgetNameSpace);
    barIndex  = fse.readJsonSync(path.join(workBenchPath,'./dist/barIndex.json'));
    if (!barIndex[widgetNameSpace]) {
      throw new Error('在barIndex.json里找不到该组件，可能路径拼写错误==>'+widgetNameSpace);
    }
    return Immutable.fromJS(barIndex[widgetNameSpace].dependenciesBar || []);
  } else {
    console.log('===================>',widgetNameSpace);
    //从阿里云拿组件所依赖的子组件
    let _path = path.join(workBenchPath,'temp/'+widgetWorkBench[0]+'/barIndex.json');
    try {
      //从阿里云拿最新的，判断和本地版本号是否一致
      let newIndex = yield download(ossPrefix.replace('${env}',envCode) + widgetWorkBench[0] + '/barIndex.json');
      if (newIndex) {
        newIndex = JSON.parse(newIndex);
      } else {
        throw new Error('从阿里云没有拿到项目'+widgetWorkBench[0]+'的barIndex.json文件');
      }

      barIndex = fse.readJsonSync(_path);
      //判断是否一致 不一致则删除temp
      if (newIndex.version !== barIndex.version) {
        barIndex = newIndex;
        let system = process.platform;
        if (system === 'win32') {
          exec('rd /s /q "' + path.join(workBenchPath,'temp/'+widgetWorkBench[0]) + '"');
        } else {
          exec('rm -rf "' + path.join(workBenchPath,'temp/'+widgetWorkBench[0]) + '"');
        }
        fse.outputJsonSync(_path, barIndex);
      }
    } catch (err) {
      console.log(ossPrefix.replace('${env}',envCode) + widgetWorkBench[0] + '/barIndex.json');
      barIndex = yield download(ossPrefix.replace('${env}',envCode) + widgetWorkBench[0] + '/barIndex.json');
      if (barIndex) {
        barIndex = JSON.parse(barIndex);
        fse.outputJsonSync(_path, barIndex);
      } else {
        throw new Error('从阿里云没有拿到项目'+widgetWorkBench[0]+'的barIndex.json文件');
      }
    }
  }

  if (!barIndex[widgetNameSpace]) {
    throw new Error('在barIndex.json文件中找不到：'+widgetNameSpace);
  }
  return Immutable.fromJS(barIndex[widgetNameSpace].dependenciesBar || []);
}

function * download(url) {
  return new Promise((resolve,reject)=>{
    http.get(url, function(res) {
      var bufferHelper = new BufferHelper();
      var data = "";
      res.on('data', function (chunk) {
        bufferHelper.concat(chunk);
      });
      res.on("end", function() {
        if (this.statusCode === 200) {
          var html = bufferHelper.toBuffer().toString();
          resolve(html);
        } else {
          resolve("");
        }
      });
    }).on("error", function(err) {
      throw new Error('请求发生错误', url);
    });
  })
}

function getNsWorkBenchName(widgetNs){
  let _all = widgetNs.split('/');
  return _all[0];
}

function getWorkBenchName(workBenchPath){
  let _all  = workBenchPath.split(path.sep);
  let workBenchName = _all[_all.length-1].trim();
  if(!workBenchName){
      workBenchName = _all[_all.length-2].trim();
  }
  return workBenchName;
}